package org.haifi.game.mina;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.haifi.game.channel.GameProcesser;
import org.haifi.game.compiler.GameParamParserFactory;
import org.haifi.game.util.SessionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.protobuf.MessageLite;

public class GameIoHandler extends IoHandlerAdapter {
	public void start() {
		if (log.isDebugEnabled()) {
			log.debug("GameIoHandlerAdapter created.");
		}
		// 手动注入gameParamParser
		gameParamParser = gameParamParserFactory.generateGameParamParse();
	}

	public void sessionCreated(IoSession session) throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("session created:" + session);
		}
		// 在网上查的，尽量不在这里添加逻辑，这里会影响到主线程
	}

	public void sessionOpened(IoSession session) throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("session opened:" + session);
		}
		// 记录session
		SessionUtils.addNewIoSession(session);
	}

	public void sessionClosed(IoSession session) throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("session closed:" + session);
		}
		// 移除session
		SessionUtils.removeIoSession(session);
	}

	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("session idle:" + session);
		}
	}

	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		if (log.isErrorEnabled()) {
			log.error("ERROR", cause);
		}
	}

	public void messageReceived(IoSession session, Object message)
			throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("message recieved:" + session.getId() + "\t" + message);
		}
		// 消息分发,到达这里时，message已经被正确的解析为对象了
		// 现在遇到一个问题，如果不使用反射，效率更高，但代码比较死板，而且不需要encoder和decoder,因为只有在取到commandId后，才可以知道对应的对象类型
		// 如果使用的反射

		GameCoderObject gameCoderObject = (GameCoderObject) message;
		
		// TODO:这里就添加验证玩家是否登陆的逻辑
		// 取出参数信息
		// Object param = GameParamUtils.parseParam(gameCoderObject.cmdId,
		// gameCoderObject.protoData);
		MessageLite param = gameParamParser.parseParam(gameCoderObject.cmdId,
				gameCoderObject.protoData);
		// 交给消息分发器处理
		gameProcesser.process(session, gameCoderObject.cmdId, param);
	}

	public void messageSent(IoSession session, Object message) throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("message send:" + session.getId() + "\t" + message);
		}
		// 消息分发,到达这里时，message已经被正确的解析为对象了
		// 现在遇到一个问题，如果不使用反射，效率更高，但代码比较死板，而且不需要encoder和decoder,因为只有在取到commandId后，才可以知道对应的对象类型
	}

	/**
	 * 这个对象是动态生成的，无法注入
	 */
	private GameParamParser gameParamParser;
	
	@Autowired
	private GameParamParserFactory gameParamParserFactory;
	@Autowired
	private GameProcesser gameProcesser;
	private static final Log log = LogFactory.getLog(GameIoHandler.class);
}
